package com.link_with_health.controller;

import com.link_with_health.common.Result;
import com.link_with_health.common.ResultCode;
import com.link_with_health.common.TokenMap;
import com.link_with_health.exception.AuthenticationFailedException;
import com.link_with_health.exception.BaseException;
import com.link_with_health.model.AdminUserEntity;
import com.link_with_health.model.Constant;
import com.link_with_health.common.CacheMap;
import com.link_with_health.model.UserEntity;
import com.link_with_health.service.AdminService;
import com.link_with_health.service.SmsService;
import com.link_with_health.service.UserService;
import com.link_with_health.utils.JsonUtil;
import com.link_with_health.utils.RandomCodeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayOutputStream;
import java.util.Map;
import java.util.HashMap;

@Controller
@RequestMapping("/api/login")
public class LoginController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private CacheMap cacheMap = CacheMap.getInstance();
    private TokenMap tokenMap = TokenMap.getInstance();

    private final String AUTH_TOKEN = "Authorization";


    @Resource
    RandomCodeUtil randomCodeUtil;

    @Resource(name = "userService")
    UserService userService;

    @Resource(name = "adminService")
    AdminService adminService;

    @Resource(name = "thirdPartySmsSender")
    SmsService tcSms;

    /**
     * 图片验证码获取接口
     * @param json 请求数据
     * @param request 请求
     * @return 数据结果
     */
    @RequestMapping("/imageCode")
    @ResponseBody
    public Result getImageCode(@RequestBody Map<String,Object> json
            , HttpServletRequest request){
        HttpSession session = request.getSession();
        String reqId = session.getId();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try{
            //String userId = String.valueOf(json.get("userId"));
            String verify = randomCodeUtil.randomImage(output);
            cacheMap.put("SessionId_"+reqId, verify.toLowerCase());
            //test
            System.out.println("SessionId_"+reqId);

            String base64 = RandomCodeUtil.outStream2base64(output);
            Map<String,String> result = new HashMap<>();

            //封装数据
            result.put("code",reqId);
            result.put("img",base64);
            return Result.success(result);
        } catch (Exception e){
            logger.error("[create img failed]");
        }
        return Result.fail("生成失败","error");
    }

    /**
     * 通过账号密码来验证
     * @param json 请求的数据
     * @param request 请求
     * @return 验证结果
     */
    @PostMapping("/verify/verifyByPassword")
    @ResponseBody
    public Result verifyByPassword(@RequestBody Map<String,Object> json
            , HttpServletRequest request){
        HttpSession session = request.getSession();
        String msg = "账号验证失败";
        try{
            String code = (String)json.get("verificationCode");
            String token = (String)json.get("token");
            String password = (String)json.get("password");

            if(code == null || !code.toLowerCase()
                    .equals(cacheMap.get("SessionId_"+token))) {
                msg  = "验证码错误！";
                throw new AuthenticationFailedException("[verify filed by verification code]");
            }
            String account =(String)json.get("account");
            //判断用户使用账号还是用户名登录
            boolean isUserId = account.matches("[0-9]+");

            UserEntity result = isUserId
                    ? userService.getUserByUserId(Long.parseLong(account))
                    : userService.getUserByUsername(account);

            //判断用户的用户状态是否能登陆
            if(userService.isInvalidStatus(result.getUserStatus()))
                throw new AuthenticationFailedException("ACCOUNT STATUS CAN'T ACCESS");
            //判断用户是否为指定ip登录
            if(isIpLock(request,result.getIpLock())){
                msg = "非法登录ip，请与系统管理员联系！";
                throw new AuthenticationFailedException("ACCOUNT LOGIN IP INVALID");
            }
            //判断用户密码是否一致
            if(!result.getPassword().equals(password)){
                throw new AuthenticationFailedException("ACCOUNT INFO CAN'T MATCH");
            }

            //保存用户的信息到tokenMap
            tokenMap.put(token,result);

            //设置用户状态为上线
            result.setUserStatus(1);
            userService.changeUser(result);
            session.setAttribute("user",result);

            //以token为key值保存用户信息
            token = token.replaceAll("SessionId_","");
            tokenMap.put(token,result);


            HashMap<String,Object> map = new HashMap<>();
            map.put("token",token);


            return Result.success(map);
        }catch (Exception e){
            logger.error("[verify failed] ",e);
            return Result.fail(msg);
        }
    }

    /**
     * 发送验证码接口
     * @param json
     * @param request
     * @return
     */
    @PostMapping("/verify/sendSms")
    @ResponseBody
    public Result sendSms(@RequestBody Map<String,Object>json
            , HttpServletRequest request){
        //以session id为token
        String token = request.getSession().getId();
        //String msg = "";
        try {
            String phone = JsonUtil.map2obj(json, String.class);
            UserEntity user = userService.getUserByPhone(phone);
            String code = String.valueOf(randomCodeUtil.randomNum(6));
            tcSms.send(phone,code);
            cacheMap.put("phone"+phone,code.toLowerCase());


            HashMap<String,String > map = new HashMap<String,String>();
            map.put("token",token);

            return Result.success(map);
        } catch (Exception e) {
            logger.error("[send sms failed]",e);

        }
        return Result.fail("发送失败");
    }


    /**
     * 手机登录校验接口
     * @param json
     * @param request
     * @return
     */
    @PostMapping("verify/verifyByPhone")
    @ResponseBody
    public Result verifyByPhone(@RequestBody Map<String,Object>json
            , HttpServletRequest request){
        String msg = "系统错误";
        try {
            String token = (String) json.get("token");
            String phone = (String) json.get("phone");
            String code = (String) json.get("smsCode");
            String sendCode = (String) cacheMap.get("phone"+phone);

            UserEntity user = userService.getUserByPhone(phone);
            cacheMap.remove(phone);

            if(sendCode.equals(code)){

                //判断用户的用户状态是否能登陆
                if(userService.isInvalidStatus(user.getUserStatus()))
                    throw new AuthenticationFailedException("ACCOUNT STATUS CAN'T ACCESS");
                //判断用户是否为指定ip登录
                if(isIpLock(request,user.getIpLock())){
                    msg = "非法登录ip，请与系统管理员联系！";
                    throw new AuthenticationFailedException("ACCOUNT LOGIN IP INVALID");
                }

                //将用户的信息保存到tokenMap
                tokenMap.put(token,user);

                //设置用户状态为上线
                user.setUserStatus(0);
                userService.changeUser(user);
                user.setPassword("******");
                logger.info("[INFO] USER_LOGIN"+user);

                HashMap<String,String> map = new HashMap<>();
                map.put("token",token);



                return Result.success(map);
            }
            msg = "账号验证失败";
        } catch (Exception e) {
            logger.error("[verify sms Code failed] ",e);
        }

        return Result.fail(msg);
    }

    /**
     * 校验管理员信息接口
     * @param json
     * @param request
     * @return
     */
    @PostMapping("verify/verifyAdminUser")
    @ResponseBody
    private Result verifyAdminUser(@RequestBody Map<String,Object> json
            , HttpServletRequest request){
        String msg = "用户验证失败";
        try{
            String token = (String) json.get("token");
            String verifyCode = (String) json.get("verifyCode");
            if(verifyCode == null || !verifyCode
                    .toLowerCase().equals(cacheMap.get("SessionId_"+token))){
                msg = "验证码错误";
                throw new AuthenticationFailedException("[verify filed" +
                        " by verification code]");
            }

            String adminName = (String)json.get("username");
            String password = (String)json.get("password");


            AdminUserEntity admin = adminService.getAdminUserByName(adminName);
            if (!admin.getAdminPW().equals(password))
                throw new AuthenticationFailedException("ACCOUNT INFO CAN'T MATCH");

            HashMap<String,String> map = new HashMap<>();
            map.put("token",token);
            System.out.println("验签 "+token);
            tokenMap.put(token,admin);

            return Result.success(map);

        } catch(Exception e){
            logger.error("[verify adminUser failed]",e);
            return Result.fail(msg);
        }

    }

    /**
     * 判断用户登录ip是否是从指定ip登录
     * @param request 请求
     * @param ip 设定的ip
     * @return 判断
     */
    private boolean isIpLock(HttpServletRequest request,String ip){
        String loginIp = request.getRemoteAddr();

        return !ip.equals(loginIp) && !ip.equals("0.0.0.0");
    }

}
